// Game.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Engine/Map.hpp>
#include <Engine/MapRenderer.hpp>
#include <Engine/TerrainMaterialManager.hpp>
#include <Engine/UnitRendererManager.hpp>
#include <engine/CamerManager.hpp>
#include <engine/LightManager.hpp>
#include <engine/World.hpp>
#include <engine/WorldRenderer.hpp>
#include <engine/Mercenary.hpp>
#include <engine/MercenaryController.hpp>
#include <engine/InputManager.hpp>

int main(int argc, char* argv[])
{
#if defined(_DEBUG)
	_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
	// Create root object
	Ogre::Root* root = new Ogre::Root;
	try
	{
		boost::filesystem::path wrk_path = boost::filesystem::initial_path();
		//  Load config
		Ogre::ConfigFile cf;
		cf.load("resources.cfg");
		// Go through all sections and settings in the file
		Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
		Ogre::String secName, typeName, archName;
		while (seci.hasMoreElements())
		{
			secName = seci.peekNextKey();
			Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
			Ogre::ConfigFile::SettingsMultiMap::iterator i;
			for (i = settings->begin(); i != settings->end(); ++i)
			{
				typeName = i->first;
				archName = i->second;
				Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
					archName, typeName, secName);
			}
		}
		// Try to load config, and if failed, show config dialog
		if(root->restoreConfig() || root->showConfigDialog())
		{
			// Create main window
			Ogre::RenderWindow* p_window = root->initialise(true, "High Explosive");
			p_window->setDeactivateOnFocusChange(false);
			// Get window metrics
			unsigned int width, height, depth;
			int top, left;
			p_window->getMetrics(width, height, depth, left, top);
			Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
			// Create the SceneManager
			Ogre::SceneManager* p_scene_manager = root->createSceneManager(Ogre::ST_GENERIC); 
			// Create the camera
			he::CameraManager camera_manager(*p_scene_manager, *p_window, "MainCam");
			camera_manager.set_camera_position(width / 50.f, height / 50.f, 5);
			// Create a light
			he::LightManager ligh_manager(*p_scene_manager);
			// Create input manager
			he::InputManager input(*p_window);

			CEGUI::OgreRenderer *p_gui_render = &CEGUI::OgreRenderer::bootstrapSystem();
			CEGUI::Imageset::setDefaultResourceGroup("Imagesets");
			CEGUI::Font::setDefaultResourceGroup("Fonts");
//			CEGUI::Scheme::setDefaultResourceGroup("Schemes");
//			CEGUI::WidgetLookManager::setDefaultResourceGroup("LookNFeel");
//			CEGUI::WindowManager::setDefaultResourceGroup("Layouts");
//			CEGUI::SchemeManager::getSingleton().create("TaharezLook.scheme");
//			CEGUI::System::getSingleton().setDefaultMouseCursor("TaharezLook", "MouseArrow");
			// Open map
			std::ifstream map_txt("map.txt");
			// Create world
			he::World world(he::Map::create_map(map_txt), "");
			// World renderer
			he::WorldRenderer world_renderer(*p_scene_manager, world);
			// Create timer
			Ogre::Timer timer;
			bool run = true;
			float last_time = 0;
			// ----
			while(run)
			{
				DWORD const start = GetTickCount();

				Ogre::WindowEventUtilities::messagePump();
				// Update input manager
				input.update();
				// Exit if key KC_ESCAPE pressed , exit
				if(input.is_key_up(OIS::KC_ESCAPE))
					run = false;
				// Switch camera
				if(input.is_key_up(OIS::KC_C))
					camera_manager.switch_debug_camera();
				// Switch to wireframe
				if(input.is_key_up(OIS::KC_W))
				{
					if(camera_manager.main_camera().getPolygonMode() == Ogre::PM_WIREFRAME)
						camera_manager.main_camera().setPolygonMode(Ogre::PM_SOLID);
					else
						camera_manager.main_camera().setPolygonMode(Ogre::PM_WIREFRAME);
				}
				// Update camera position
				{
					Ogre::Vector3 translate_camera = Ogre::Vector3::ZERO;
					if(input.is_key_down(OIS::KC_UP))
						translate_camera = Ogre::Vector3(0, 0, -1);
					else if(input.is_key_down(OIS::KC_DOWN))
						translate_camera = Ogre::Vector3(0, 0, 1);
					else if(input.is_key_down(OIS::KC_LEFT))
						translate_camera = Ogre::Vector3(-1, 0, 0);
					else if(input.is_key_down(OIS::KC_RIGHT))
						translate_camera = Ogre::Vector3(1, 0, 0);
					// Only if need to move
					if(translate_camera != Ogre::Vector3::ZERO)
						camera_manager.move_main_camera_relative(translate_camera);
				}
				// Let the framework update data
				float new_time = timer.getMilliseconds() / 1000.f;
				float delta = new_time - last_time;
				world_renderer.update(delta);
				last_time = new_time;
				// Render frame
				root->renderOneFrame();


				DWORD const end = GetTickCount();
				auto const time_diff = end - start;
				if(time_diff < 33)
					Sleep(33 - time_diff);
			}
			CEGUI::OgreRenderer::destroySystem();
		}
	}
	catch(std::exception const &e)
	{
		std::cout << "Exception caught: " << e.what() << std::endl;
	}
	//Ogre
	delete root;


	return 0;
}

